package com.zzb.framework.multiplysubmit;

import com.zzb.framework.cache.CacheComponent;
import com.zzb.framework.multiplysubmit.annotation.MultiplySubmit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;

/**
 * 防止表单重复提交的拦截器
 * Created by zhangzhenbin on 2016/11/24.
 */
@Component
public class MultiplySubmitInterceptor implements HandlerInterceptor {
    private static Logger logger = LoggerFactory.getLogger(MultiplySubmitInterceptor.class);
    private static Exception SUBMIT_MULTIPLY_ERROR = new Exception("您操作的太快了，喝一杯JAVA休息一下吧");
    @Autowired
    CacheComponent cacheComponent;
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
        MultiplySubmit mutiplySubmit=null;
        //表单重复提交注解，则不能一秒内重复提交
        try {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            mutiplySubmit = method.getAnnotation(MultiplySubmit.class);
            if(mutiplySubmit == null){
                return true;
            }
        } catch (Exception e) {
            return true;
        }

        HttpSession session = httpServletRequest.getSession();
        String id = session.getId();
        logger.info("浏览器sessionId:"+id);
        //提交请求概要
        SubmitRequestReference reference = new SubmitRequestReference();
        reference.setIp(getRemortIP(httpServletRequest));
        reference.setSessionId(id);
        reference.setUri(httpServletRequest.getRequestURI());
        reference.setUrl(httpServletRequest.getRequestURL().toString());
        String key = id + reference.hashCode();
        logger.info(key);
        //如果已经存在请求，则不给提交
        boolean exist = cacheComponent.exist("SubmitRequestReferenceCache", key, SubmitRequestReference.class);
        if(exist){
            logger.error("重复提交表单");
            throw  SUBMIT_MULTIPLY_ERROR;
        }
        //默认三秒内不能重复提交
        cacheComponent.put("SubmitRequestReferenceCache",key,reference,mutiplySubmit.value ());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
    private String getRemortIP(HttpServletRequest request) {
        if (request.getHeader("x-forwarded-for") == null) {
            return request.getRemoteAddr();
        }
        return request.getHeader("x-forwarded-for");
    }
}
